﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Mvc.Resources;
using System.Web.WebPages;
using System.Globalization;
using System.Web.Helpers;

namespace HelloMVC.Model
{

    public class IconSelectListItem : SelectListItem
    {
        public String IconName { get; set; }
        public String IconClass { get { return "imagebacked icon-" + IconName; } }
    }

    public static class CustomHtmlHelper
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString AutocompleteFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            var autocompleValues = metadata.AdditionalValues;
            htmlAttributes = htmlAttributes ?? new Dictionary<string, object>();
            htmlAttributes.Add("auto-value", "true");
            htmlAttributes.Add("auto-rel", autocompleValues.ContainsKey("auto-rel") ? autocompleValues["auto-rel"] : "");
            htmlAttributes.Add("auto-service", autocompleValues.ContainsKey("auto-service") ? autocompleValues["auto-service"] : "AutoService");
            return htmlHelper.TextBoxFor<TModel, TProperty>(expression, htmlAttributes);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static MvcHtmlString AutocompleteFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.AutocompleteFor<TModel, TProperty>(expression, ((IDictionary<string, object>)null));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString AutocompleteFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.AutocompleteFor<TModel, TProperty>(expression, ((IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="iconSelectList"></param>
        /// <returns></returns>
        public static MvcHtmlString IconDropdownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            IEnumerable<IconSelectListItem> iconSelectList)
        {
            return htmlHelper.IconDropdownListFor<TModel, TProperty>(expression, iconSelectList, ((IDictionary<string, object>)null));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="iconSelectList"></param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString IconDropdownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            IEnumerable<IconSelectListItem> iconSelectList,
            object htmlAttributes)
        {
            return htmlHelper.IconDropdownListFor<TModel, TProperty>(expression, iconSelectList, ((IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString IconDropdownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            IEnumerable<IconSelectListItem> iconSelectList,
            IDictionary<string, object> htmlAttributes)
        {
            ModelState state;
            var name = ExpressionHelper.GetExpressionText(expression);
            var fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            var value = htmlHelper.ViewData.Eval(fullName);

            StringBuilder builder = new StringBuilder();
            foreach (var item in iconSelectList)
            {
                if (item.Value.Equals(value))
                {
                    item.Selected = true;
                }

                builder.AppendLine(ListItemToOption(item));
            }


            TagBuilder tagBuilder = new TagBuilder("select");
            tagBuilder.InnerHtml = builder.ToString();
            tagBuilder.MergeAttributes<string, object>(htmlAttributes);
            tagBuilder.MergeAttribute("name", fullName, true);
            tagBuilder.GenerateId(fullName);

            if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out state) && (state.Errors.Count > 0))
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }

            tagBuilder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(name));

            return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="key"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        internal static object GetModelStateValue(HtmlHelper htmlHelper, string key, Type destinationType)
        {
           
            ModelState state;
            if (htmlHelper.ViewData.ModelState.TryGetValue(key, out state) && (state.Value != null))
            {
                return state.Value.ConvertTo(destinationType, null);
            }
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        internal static string ListItemToOption(IconSelectListItem item)
        {
            TagBuilder builder = new TagBuilder("option");

            builder.InnerHtml = HttpUtility.HtmlEncode(item.Text);
            if (item.Value != null)
            {
                builder.Attributes["value"] = item.Value;
            }

            if (item.Selected)
            {
                builder.Attributes["selected"] = "selected";
            }

            if (!String.IsNullOrWhiteSpace(item.IconName))
            {
                builder.Attributes["class"] = item.IconClass;
            }

            return builder.ToString(TagRenderMode.Normal);
        }


        //private static MvcHtmlString TextBoxHelper(this HtmlHelper htmlHelper, ModelMetadata metadata, object model, string expression, IDictionary<string, object> htmlAttributes)
        //{
        //    return new MvcHtmlString(InputTagHelper(htmlHelper, InputType.Text, metadata, expression, model, false, false, true, true, htmlAttributes).ToString(TagRenderMode.SelfClosing));
        //}

        //private static object GetModelStateValue(this HtmlHelper htmlHelper, string key, Type destinationType)
        //{
        //    ModelState state;
        //    if (htmlHelper.ViewData.ModelState.TryGetValue(key, out state) && (state.Value != null))
        //    {
        //        return state.Value.ConvertTo(destinationType, null);
        //    }
        //    return null;
        //}

        //private static string EvalString(this HtmlHelper htmlHelper, string key)
        //{
        //    return Convert.ToString(htmlHelper.ViewData.Eval(key), CultureInfo.CurrentCulture);
        //}

        //private static bool EvalBoolean(this HtmlHelper htmlHelper, string key)
        //{
        //    return Convert.ToBoolean(htmlHelper.ViewData.Eval(key), CultureInfo.InvariantCulture);
        //}


        //private static TagBuilder InputTagHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, IDictionary<string, object> htmlAttributes)
        //{
        //    ModelState state;
        //    string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

        //    if (string.IsNullOrEmpty(fullHtmlFieldName))
        //    {
        //        throw new ArgumentException("Full Html Field Name is null", "name");
        //    }

        //    TagBuilder tagBuilder = new TagBuilder("input");
        //    tagBuilder.MergeAttributes<string, object>(htmlAttributes);
        //    tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
        //    tagBuilder.MergeAttribute("name", fullHtmlFieldName, true);
        //    string str2 = Convert.ToString(value, CultureInfo.CurrentCulture);
        //    string str4 = (string)htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(string));

        //    tagBuilder.MergeAttribute("value", str4 ?? (useViewData ? htmlHelper.EvalString(fullHtmlFieldName) : str2), isExplicitValue);

        //    if (setId)
        //    {
        //        tagBuilder.GenerateId(fullHtmlFieldName);
        //    }
        //    if (htmlHelper.ViewData.ModelState.TryGetValue(fullHtmlFieldName, out state) && (state.Errors.Count > 0))
        //    {
        //        tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
        //    }
        //    tagBuilder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));

        //    return tagBuilder;
        //}
    }
}
